namespace OFX.Aggregator.WpfApplication
{
	#region #using Directives

	using System;
	using System.Reflection;
	using System.Runtime.Serialization;
	using System.Text.RegularExpressions;

	#endregion

	internal class OFXSerializationBinder : SerializationBinder
	{
		#region Overrides of SerializationBinder

		/// <summary>
		/// When overridden in a derived class, controls the binding of a serialized object to a type.
		/// </summary>
		/// <returns>
		/// The type of the object the formatter creates a new instance of.
		/// </returns>
		/// <param name="assemblyName">
		/// Specifies the <see cref="T:System.Reflection.Assembly" /> name of the serialized object. 
		/// </param>
		/// <param name="typeName">
		/// Specifies the <see cref="T:System.Type" /> name of the serialized object. 
		/// </param>
		public override Type BindToType(string assemblyName, string typeName)
		{
			handle04to05Revision(ref assemblyName, ref typeName);
			handle05xxxto05Revision(ref assemblyName, ref typeName);

			return Assembly.Load(assemblyName).GetType(typeName);
		}

		private static void handle04to05Revision(ref string assemblyName, ref string typeName)
		{
			if (typeName == "OFX.Aggregator.Implementation.StatementSourceRepository" &&
			    assemblyName == "OFX.Aggregator.Implementation, Version=0.4.0.0, Culture=neutral, PublicKeyToken=67a072ef21812023")
			{
				assemblyName = assemblyName.Replace("0.4.0.0", "0.5");
			}

			if (typeName == "OFX.Aggregator.Infrastructure.StatementSource" &&
			    assemblyName == "OFX.Aggregator.Infrastructure, Version=0.4.0.0, Culture=neutral, PublicKeyToken=67a072ef21812023")
			{
				assemblyName = assemblyName.Replace("0.4.0.0", "0.5");
			}

			if (
				typeName.Contains(
					"OFX.Aggregator.Infrastructure.StatementSource, OFX.Aggregator.Infrastructure, Version=0.4.0.0, Culture=neutral, PublicKeyToken=67a072ef21812023"))
			{
				typeName = typeName.Replace("OFX.Aggregator.Infrastructure, Version=0.4.0.0", "OFX.Aggregator.Infrastructure, Version=0.5");
			}
		}

		private static void handle05xxxto05Revision(ref string assemblyName, ref string typeName)
		{
			migrateAssemblyVersion("OFX.Aggregator.Implementation", ref assemblyName);
			migrateAssemblyVersion("OFX.Aggregator.Implementation", ref typeName);

			migrateAssemblyVersion("OFX.Aggregator.Infrastructure", ref assemblyName);
			migrateAssemblyVersion("OFX.Aggregator.Infrastructure", ref typeName);
		}

		private static void migrateAssemblyVersion(string assembly, ref string version)
		{
			var targetVersion = assembly + ", Version=0.5";

			version = Regex.Replace(version, Regex.Unescape(assembly) + @", Version=0\.5\.\d{3,5}.\d{3,5}", targetVersion);
		}

		#endregion
	}
}